package com.clp.protocol.modbus_tcp.client.async;

import com.clp.protocol.modbus_tcp.client.Master;

import java.util.LinkedList;
import java.util.List;

/**
 * 通用的 MasterPromise
 * @param <V>
 */
public abstract class GenericMasterPromise<P extends GenericMasterPromise<P, V>, V> implements MasterPromise<V> {

    protected volatile boolean isDone = false;
    protected volatile boolean isSuccess = false;
    protected volatile V res = null;
    protected volatile Throwable cause = null;
    protected final List<MasterFutureListener<V>> listeners = new LinkedList<>();

    private final Master master;

    protected GenericMasterPromise(Master master) {
        this.master = master;
    }

    @Override
    public Master master() {
        return master;
    }

    @SuppressWarnings("unchecked")
    protected P self() {
        return ((P) this);
    }

    @Override
    public boolean isDone() {
        return isDone;
    }

    @Override
    public boolean isSuccess() {
        return isDone() && isSuccess;
    }

    @Override
    public V getRes() {
        return res;
    }

    @Override
    public P setRes(V val) {
        synchronized (this) {
            this.res = val;
            return self();
        }
    }

    /**
     * 只会设置一次，重复设置第2次无效
     * @return
     */
    @Override
    public P setSuccess() {
        synchronized (this) {
            if (this.isDone()) return self();
            this.isSuccess = true;
            this.isDone = true;

            notifyAllListeners();
            this.notifyAll();
            return self();
        }
    }

    /**
     * 只会设置一次，重复设置第2次无效
     * @param cause
     * @return
     */
    @Override
    public P setFailure(Throwable cause) {
        synchronized (this) {
            if (this.isDone()) return self();
            this.isSuccess = false;
            this.cause = cause;
            this.isDone = true;

            notifyAllListeners();
            this.notifyAll();
            return self();
        }
    }

    @Override
    public P addListener(MasterFutureListener<V> listener) {
        synchronized (this) {
            listeners.add(listener);
            if (this.isDone()) {
                notifyAllListeners();
            }
            return self();
        }
    }
    /**
     * 通知所有监听器
     */
    protected void notifyAllListeners() {
        master().executorService().submit(() -> {
            synchronized (this) {
                for (MasterFutureListener<V> listener : listeners) {
                    listener.operationComplete(self());
                }
                listeners.clear();
            }
        });
    }

    @Override
    public P sync() {
        synchronized (this) {
            while (!isDone()) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return self();
        }
    }

    @Override
    public P sync(int timeoutMs) {
        synchronized (this) {
            long beginMs = System.currentTimeMillis();
            long passedMs = 0;
            while (!isDone()) {
                long waitMs = timeoutMs - passedMs;
                if (waitMs <= 0) break;
                try {
                    this.wait(waitMs);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                passedMs = System.currentTimeMillis() - beginMs;
            }
        }
        return self();
    }

    @Override
    public Throwable cause() {
        return cause;
    }
}
